import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { RadioModule } from './radio.module';

@Component({
  template: `
    <label lv-radio [lvViewType]="lvViewType" [ngModel]="false" [lvDisabled]="lvDisabled">Radio</label>
    <button (click)="check('item002')">click</button>
    <lv-radio-group [(ngModel)]="selected" [lvDisabled]="lvDisabled" [lvGroupName]="'group'">
      <lv-radio [lvViewType]="lvViewType" [lvValue]="'item001'" [lvControl]="lvControl">Item001</lv-radio>
      <lv-radio [lvViewType]="lvViewType" [lvValue]="'item002'" [lvControl]="lvControl">Item002</lv-radio>
    </lv-radio-group>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
class TestRadioComponent {
  selected = 'item001';

  @Input() lvDisabled = false;
  @Input() lvViewType = 'default';
  @Input() lvControl = false;

  check(val) {
    this.selected = val;
  }
}

describe('RadioComponent', () => {
  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        declarations: [TestRadioComponent],
        imports: [RadioModule, FormsModule],
        teardown: { destroyAfterEach: false },
      }).compileComponents();
    })
  );

  describe('render', () => {
    let component: TestRadioComponent;
    let fixture: ComponentFixture<TestRadioComponent>;
    const renderComp = fakeAsync(para => {
      for (const [key, value] of Object.entries(para)) {
        component[key] = value;
      }
      fixture.detectChanges();
      tick(1500);
      fixture.detectChanges();
      expect(fixture).toMatchSnapshot();
    });

    beforeEach(() => {
      fixture = TestBed.createComponent(TestRadioComponent);
      component = fixture.componentInstance;
    });

    // disabled状态渲染
    it('with lvDisabled', () => {
      renderComp({ lvDisabled: true });
    });

    it('with lvViewType is button', () => {
      renderComp({ lvViewType: 'button' });
    });

    it('with lvViewType is link', () => {
      renderComp({ lvViewType: 'link' });
    });
  });

  describe('work', () => {
    let component: TestRadioComponent;
    let fixture: ComponentFixture<TestRadioComponent>;
    const checkedClass = '.lv-checkbase-checked';

    beforeEach(() => {
      fixture = TestBed.createComponent(TestRadioComponent);
      component = fixture.componentInstance;
    });

    // 正常选择切换
    it('should work when click', fakeAsync(() => {
      fixture.detectChanges();
      tick(1500);
      fixture.detectChanges();
      const checkedItem = fixture.nativeElement.querySelector(checkedClass);
      expect(checkedItem.textContent).toContain('Item001');

      const radio2 = fixture.nativeElement.querySelectorAll('lv-radio')[1];
      radio2.dispatchEvent(new Event('click'));
      fixture.detectChanges();
      tick(1500);
      fixture.detectChanges();
      const checkedItem2 = fixture.nativeElement.querySelector(checkedClass);
      expect(checkedItem2.textContent).toContain('Item002');
    }));

    // 状态外部控制测试
    it('should work with lvControl', fakeAsync(() => {
      component.lvControl = true;
      fixture.detectChanges();
      tick(1500);

      // 直接选择radio没法选中
      const radio2 = fixture.nativeElement.querySelectorAll('lv-radio')[1];
      radio2.dispatchEvent(new Event('click'));
      fixture.detectChanges();
      tick(1500);
      fixture.detectChanges();
      const checkedItem = fixture.nativeElement.querySelector(checkedClass);
      expect(checkedItem.textContent).toContain('Item001');

      // 外部button控制
      const button = fixture.nativeElement.querySelector('button');
      button.dispatchEvent(new Event('click'));
      fixture.detectChanges();
      tick(1500);
      fixture.detectChanges();
      const checkedItem2 = fixture.nativeElement.querySelector(checkedClass);
      expect(checkedItem2.textContent).toContain('Item002');
    }));
  });
});
